package ap.project.controller.service;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import ap.project.controller.main.Connection;
import ap.project.controller.main.Constants;
import ap.project.controller.main.VotingActivity;

public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {

	public static Context context;
	private GameThread thread;
	private GameControls controls;
	private GameResources joystick;
	private String PLAYERNAME;
	private Paint p = new Paint();
	private boolean retry;
	public static int[] votes;
	public static int health = 100;
	static boolean showPowerUp1 = false;
	static boolean showPowerUp2 = false;
	static boolean showPowerUp3 = false;

	/**
	 * Construct gamesurface, set context and set player name
	 * 
	 * @param context
	 * @param name - playername
	 */
	public GameSurface(Context context, String name) {
		super(context);
		votes = new int[]{0,0,0};
		GameSurface.context = context;
		this.PLAYERNAME = name;

		// send player name
		JSONObject jOb = createJsonData(Constants.CODENAME);
		Connection.getInstance().send(jOb);

		// set up game resources
		init();
	}

	/**
	 * Create a JSONObjet based on the communicationCode
	 * 
	 * @param communicationCode
	 * @return JSONObject
	 */
	private JSONObject createJsonData(int communicationCode) {
		JSONObject jOb = new JSONObject();

		try {
			if (communicationCode == 0) {
				jOb.put("Code", communicationCode);
				jOb.put("Angle", calculateAngle());
				jOb.put("Speed", calculateSpeed());
				jOb.put("Shoot", controls.shooting);
			} else if (communicationCode == 1) {
				jOb.put("Code", communicationCode);
				jOb.put("Powerup", controls.powerup);
			} else if (communicationCode == 2) {
				jOb.put("Code", communicationCode);
				jOb.put("Vote", "1");
			} else if (communicationCode == 3) {
				jOb.put("Code", communicationCode);
				jOb.put("Name", this.PLAYERNAME);
			} else {
				jOb = null;
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return jOb;
	}

	/**
	 * returns the angle based on the point of origin against the touchpoint
	 * 
	 * @return angle
	 */
	private double calculateAngle() {
		double angle = Math.atan2(
				controls.touchingPoint.y - Constants.STARTY,
				controls.touchingPoint.x - Constants.STARTX)
				/ (Math.PI / 180);
		return angle;
	}

	/**
	 * returns the speed using the distance between the point of origin against the touching point
	 * 
	 * @return
	 */
	private int calculateSpeed() {
		double dY = controls.touchingPoint.y - Constants.STARTY;
		double dX = controls.touchingPoint.x - Constants.STARTX;
		return (int) (Math.sqrt((Math.abs(dY) * 2) + (Math.abs(dX * 2))));
	}

	private void init() {
		SurfaceHolder holder = getHolder();
		holder.addCallback(this);

		setFocusable(true);

		thread = new GameThread(holder, context, new Handler(), this);
		joystick = new GameResources(getContext().getResources());
		controls = new GameControls(context);

		setOnTouchListener(controls);
	}

	/**
	 * Draw the new image on the canvas.
	 * @param canvas
	 */
	public void doDraw(Canvas canvas) {
		canvas.drawBitmap(joystick.getHealthBg(), Constants.HEALTHBGX, Constants.HEALTHBGY, null);
		canvas.drawBitmap(joystick.getNameBg(), Constants.NAMEBGX , Constants.NAMEBGY, null);
		p.setAntiAlias(true);
		p.setTextSize(20f);
		p.setColor(Color.argb(255, 245, 155, 0));
		canvas.drawText(this.PLAYERNAME, Constants.NAMEX, Constants.NAMEY, p);
		p.setColor(Color.argb(255, 255, 0, 0));

		// Check if data to be send is not already sent.
		if (controls.outdated) {
			JSONObject jOb;
			if (controls.powerup > 0) {
				jOb = createJsonData(1);
				controls.powerup = 0;
			} else {
				jOb = createJsonData(0);
			}
			Connection.getInstance().send(jOb);
			controls.outdated = false;
		}
		
		if(GameSurface.health == 3) {
			canvas.drawBitmap(joystick.getHearth(),
					Constants.HEARTH3X, Constants.HEARTH3Y, null);
		}
		
		if(GameSurface.health >= 2) {
			canvas.drawBitmap(joystick.getHearth(),
					Constants.HEARTH2X, Constants.HEARTH2Y, null);
		}
		
		if(GameSurface.health >= 1) {
			canvas.drawBitmap(joystick.getHearth(),
					Constants.HEARTH1X, Constants.HEARTH1Y, null);
		}
		
		if (showPowerUp1)
			canvas.drawBitmap(joystick.getPowerUp1(),
					Constants.STARTPOWERUPX1, Constants.POWERUPY, null);

		if (showPowerUp2)
			canvas.drawBitmap(joystick.getPowerUp2(),
					Constants.STARTPOWERUPX2, Constants.POWERUPY, null);

		if (showPowerUp3)
			canvas.drawBitmap(joystick.getPowerUp3(),
					Constants.STARTPOWERUPX3, Constants.POWERUPY, null);
		
		if(controls.shooting) {
			canvas.drawBitmap(joystick.getButtonShoot(), Constants.STARTBUTTONX,
				Constants.STARTBUTTONY, null);
		} else {
			canvas.drawBitmap(joystick.get_shootButton(), Constants.STARTBUTTONX,
					Constants.STARTBUTTONY, null);
		}
		
		// draw the joystick background
		canvas.drawBitmap(joystick.get_joystickBg(), Constants.STARTX
				- Constants.BACKGROUNDRADIUS, Constants.STARTY
				- Constants.BACKGROUNDRADIUS, null);

		// draw the dragable joystick
		canvas.drawBitmap(joystick.get_joystick(), controls.touchingPoint.x
				- Constants.JOYSTICKRADIUS, controls.touchingPoint.y
				- Constants.JOYSTICKRADIUS, null);
		//canvas.drawBitmap(_joystick.getBackground(), 0, 0, null);

		postInvalidate(); 
	}

	// these methods are overridden from the SurfaceView super class. They are
	// automatically called
	// when a SurfaceView is created, resumed or suspended.
	
	/*
	 * (non-Javadoc)
	 * @see android.view.SurfaceHolder.Callback#surfaceChanged(android.view.SurfaceHolder, int, int, int)
	 */
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 
	}

	/*
	 * (non-Javadoc)
	 * @see android.view.SurfaceHolder.Callback#surfaceDestroyed(android.view.SurfaceHolder)
	 */
	public void surfaceDestroyed(SurfaceHolder arg0) {
		retry = true;
	
		thread.state = GameThread.STOPPED;
		while (retry) {
			try {
				// code to kill Thread
				thread.join();
				retry = false;
			} catch (InterruptedException e) {
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * @see android.view.SurfaceHolder.Callback#surfaceCreated(android.view.SurfaceHolder)
	 */
	public void surfaceCreated(SurfaceHolder arg0) {
		if (thread.state == GameThread.PAUSED) {
			// When game is opened again in the Android OS
			thread = new GameThread(getHolder(), context, new Handler(), this);
			thread.start();
		} else {
			// creating the game Thread for the first time
			thread.start();
		}
	}

	/**
	 * Set the votes based on the votes from the incoming packet
	 * 
	 * @param vote
	 */
	public static void setVotingScreen(int[] vote) {
		votes[0] = vote[0];		
		votes[1] = vote[1];	
		votes[2] = vote[2];	
	}

	private static void startVoteActivity(){
		Intent voting = new Intent(context.getApplicationContext(),
				VotingActivity.class);
		voting.putExtra("game1", votes[0]); 
		voting.putExtra("game2", votes[1]);
		voting.putExtra("game3", votes[2]);
		context.startActivity(voting);

	}
	
	/**
	 * 
	 * @param powerUp
	 * @param setShow
	 */
	public static void handlePowerUp(int powerUp, boolean setShow) {
		switch (powerUp) {
		case 1:
			showPowerUp1 = setShow;
			break;

		case 2:
			showPowerUp2 = setShow; 
			break;

		case 3:
			showPowerUp3 = setShow;
			break;
			
		default:
			break;
		}
	}

	/**
	 * Set activity based on the game state which has been received from the server
	 * 
	 * @param state
	 */
	public static void ActivityHandler(int state) {
		closeExtraActivities();
		switch (state) {
		case Constants.STATEVOTING:
			startVoteActivity();
			break;

		case Constants.STATEPAINTBALL:			
			break;

		case Constants.STATECHASE:	
			break;
			
		case Constants.STATEBALLPOOL:	
			break;
			
		case Constants.STATECREDITS:		
			break;
			
		default:
			break;
		}
	}

	/**
	 * Need to be called when starting any other activity so that they dont overlap.
	 */
	private static void closeExtraActivities() {
		if(VotingActivity.handleToClose != null){
			VotingActivity.handleToClose.finish();
		}

	}

}
